﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace SmartMathLibrary
{
    /// <summary>
    /// This class provides the splitting of a natural number in its factors. It use an iterative way 
    /// and checks all divisors of a number.
    /// </summary>
    [Serializable]
    public class SimpleNumberFactorizer : AbstractNumberFactorizer
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="SimpleNumberFactorizer"/> class.
        /// </summary>
        /// <param name="number">The number to factorize.</param>
        public SimpleNumberFactorizer(UInt64 number)
            : base(number)
        {
        }

        /// <summary>
        /// Factorizes the specified number.
        /// </summary>
        /// <returns>The factors of the number.</returns>
        public override UInt64[] Factorize()
        {
            bool runProcess = true;
            NumberFactors tempuri;
            UInt64 currentNumber = this.Number;
            List<UInt64> result = new List<UInt64>();

            while (runProcess)
            {
                tempuri = FactorizeNumber(currentNumber);

                if ((tempuri.FirstFactor == 0) && (tempuri.SecondFactor == 0))
                {
                    runProcess = false;
                    continue;
                }

                currentNumber = tempuri.FirstFactor;
                result.Add(tempuri.SecondFactor);
            }

            result.Add(currentNumber);

            return result.ToArray();
        }

        /// <summary>
        /// Factorizes the specified number.
        /// </summary>
        /// <param name="number">The number to factorize.</param>
        /// <returns>The two factors of the number.</returns>
        private static NumberFactors FactorizeNumber(UInt64 number)
        {
            UInt64 factor = 2;
            NumberFactors result = new NumberFactors();

            while (factor < number)
            {
                if (number % factor == 0)
                {
                    result.FirstFactor = number / factor;
                    result.SecondFactor = factor;

                    return result;
                }

                factor++;
            }

            return result;
        }
    }
}